#include "../inc/CoordF.h"

CoordF::CoordF() {
  x = y = z = 0.0; w = 1.0;
}

CoordF::CoordF(const CoordF &c) :
  x(c.x), y(c.y), z(c.z), w(c.w)
{
}

CoordF::CoordF(GLfloat f)
{
  vec(f);
}

CoordF::CoordF(GLfloat nx, GLfloat ny, GLfloat nz, GLfloat nw)
{
  vec(nx, ny, nz, nw);
}

CoordF::CoordF(GLfloat nx, GLfloat ny, GLfloat nz)
{
  vec(nx, ny, nz);
}

CoordF::CoordF(GLfloat nx, GLfloat ny)
{
  vec(nx, ny);
}

CoordF::CoordF(const GLfloat vec[3])
{
  x = (GLfloat) vec[0];
  y = (GLfloat) vec[1];
  z = (GLfloat) vec[2];
  w = 1.0;
}

CoordF::CoordF(const CoordF& v1,const CoordF& v2)
{
  cross(v1,v2);
}

CoordF::~CoordF()
{
}

void CoordF::null(void)
{
  x=y=z=0; w=1; 
}

void CoordF::operator =(const CoordF &in)
{
  x = in.x; y = in.y; z = in.z; w = in.w; 
}

CoordF CoordF::operator -() const
{
  return CoordF(-x,-y,-z);
}

CoordF CoordF::operator +(const CoordF &a) const
{
  return CoordF(x + a.x, y + a.y, z + a.z);
}

CoordF CoordF::operator -(const CoordF &a) const
{
  return CoordF(x - a.x, y - a.y, z - a.z);
}

CoordF CoordF::operator *(const GLfloat &a) const
{
  return CoordF(x * a, y * a, z * a);
}

CoordF CoordF::operator *(const CoordF &v) const
{ 
  return CoordF(x*v.x,y*v.y,z*v.z);
}

CoordF CoordF::operator /(const GLfloat &a) const
{
  GLfloat inv_a = 1.0/a;
  return CoordF(x * inv_a, y * inv_a, z * inv_a);
}

CoordF CoordF::operator /(const CoordF &v) const
{
  return CoordF(x/v.x,y/v.y,z/v.z); 
}

void CoordF::operator -=(const CoordF &v)
{
	x -= v.x; y -= v.y; z -= v.z; 
}

void CoordF::operator +=(const CoordF &v)
{
	x += v.x; y += v.y; z += v.z;
}


void CoordF::operator *=(const GLfloat &f)
{
	x *= f; y *= f; z *= f;
}

void CoordF::operator /=(const GLfloat &f)
{
    float inv_f = 1.0/f;
	x *= inv_f; y *= inv_f; z *= inv_f;
}

GLfloat& CoordF::operator[](int i)
{
  return (&x)[i]; 
}

GLfloat CoordF::operator[](int i) const
{
  return (&x)[i]; 
}

bool CoordF::operator ==(const CoordF &v) const
{
	if (x != v.x) return false;
	if (y != v.y) return false;
	if (z != v.z) return false;
	if (w != v.w) return false;
	return true;
}

bool CoordF::operator !=(const CoordF &v) const
{
	if (x != v.x) return true;
	if (y != v.y) return true;
	if (z != v.z) return true;
	if (w != v.w) return true;
	return false;
}

void CoordF::vec(GLfloat f)
{
  x=y=z=f; w=1.0;
}

void CoordF::vec(GLfloat nx, GLfloat ny, GLfloat nz, GLfloat nw)
{
  x=nx; y=ny; z=nz; w=nw;
}

void CoordF::vec(GLfloat nx, GLfloat ny, GLfloat nz)
{
  x=nx; y=ny; z=nz; w=1.0;
}

void CoordF::vec(GLfloat nx, GLfloat ny)
{
  x=nx; y=ny; z=0.0; w=1.0;
}

GLfloat CoordF::dot(const CoordF &a)
{
  return (x*a.x + y*a.y + z*a.z);
}

void CoordF::cross(const CoordF &v1, const CoordF &v2)
{
   x=v1.y*v2.z-v1.z*v2.y;
   y=v1.z*v2.x-v1.x*v2.z;
   z=v1.x*v2.y-v1.y*v2.x;
}

CoordF CoordF::cross(const CoordF &v2) const
{
   const CoordF &v1 = *this;
   return CoordF (v1.y*v2.z - v1.z*v2.y,
				  v1.z*v2.x - v1.x*v2.z,
				  v1.x*v2.y - v1.y*v2.x);
}

GLfloat CoordF::len2()
{
  return (x*x + y*y + z*z);
}

GLfloat CoordF::len()
{
  return (sqrt(len2()));
}

void CoordF::negate()
{
  x=-x; y=-y; z=-z; 
}

void CoordF::normalize()
{
  GLfloat tf = len();
  
  x /= tf;
  y /= tf;
  z /= tf;
}

void CoordF::rotateInX( GLfloat angle )
{
     GLfloat rad = toRadians(angle);
     GLfloat tempY = y;
     GLfloat tempZ = z;
     
     y = tempY * cos(rad) - tempZ * sin(rad);
     z = tempY * sin(rad) + tempZ * cos(rad);
}

void CoordF::rotateInY( GLfloat angle )
{
     GLfloat rad = toRadians(angle);
     GLfloat tempX = x;
     GLfloat tempZ = z;
     
     z = tempZ * cos(rad) - tempX * sin(rad);
     x = tempZ * sin(rad) + tempX * cos(rad);
}

void CoordF::rotateInZ( GLfloat angle )
{
     GLfloat rad = toRadians(angle);
     GLfloat tempX = x;
     GLfloat tempY = y;
     
     x = tempX * cos(rad) - tempY * sin(rad);
     y = tempX * sin(rad) + tempY * cos(rad);
}
